package com.whereta.service.impl;

import com.whereta.dao.*;
import com.whereta.model.Menu;
import com.whereta.model.Permission;
import com.whereta.model.Role;
import com.whereta.service.IPermissionService;
import com.whereta.vo.PermissionCreateVO;
import com.whereta.vo.PermissionEditVO;
import com.whereta.vo.ResultVO;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author Vincent
 * @time 2015/8/28 9:45
 */
@Service("permissionService")
public class PermissionServiceImpl implements IPermissionService {
    @Resource
    private IPermissionDao permissionDao;
    @Resource
    private IRolePermissionDao rolePermissionDao;
    @Resource
    private IMenuPermissionDao menuPermissionDao;
    @Resource
    private IMenuDao menuDao;
    @Resource
    private IRoleDao roleDao;

    /**
     * 删除权限
     *
     * @param perId
     * @return
     */
    public ResultVO delPermission(int perId) {
        ResultVO resultVO = new ResultVO(true);
        //获取所有权限
        List<Permission> permissionList = permissionDao.selectAll();
        Permission permission = permissionDao.get(permissionList, perId);
        if (permission == null) {
            resultVO.setOk(false);
            resultVO.setMsg("权限不存在");
            return resultVO;
        }
        //查看是否有权限
        Subject subject = SecurityUtils.getSubject();
        if (!subject.isPermitted(permission.getKey())) {
            resultVO.setOk(false);
            resultVO.setMsg("您没有操作权限");
            return resultVO;
        }
        //判断是否是根级权限
        //获取我拥有的权限
        List<Permission> myPermissionList = new ArrayList<Permission>();
        for (Permission p : permissionList) {
            String key = p.getKey();
            boolean permitted = subject.isPermitted(key);
            if (permitted) {
                myPermissionList.add(p);
            }
        }
        List<Permission> rootPermissions = getRootPermissions(myPermissionList);
        for (Permission p : rootPermissions) {
            if (p.getId().intValue() == perId) {
                resultVO.setOk(false);
                resultVO.setMsg("根级权限不能删除");
                return resultVO;
            }
        }


        //获取子级权限id集合
        List<Integer> childrenPermissionIds = getChildrenPermissionIds(perId, permissionList);

        //删除权限
        int num = permissionDao.deletePermission(perId);

        for (Integer id : childrenPermissionIds) {
            num = permissionDao.deletePermission(id);
            if (num == 1) {
                rolePermissionDao.deleteByPerId(id);
                menuPermissionDao.deleteByPerId(id);

            }
        }
        rolePermissionDao.deleteByPerId(perId);
        menuPermissionDao.deleteByPerId(perId);
        resultVO.setMsg("删除权限成功");
        return resultVO;
    }

    /**
     * 获取子级权限id集合
     *
     * @param parentId
     * @param permissions
     * @return
     */
    public static List<Integer> getChildrenPermissionIds(Integer parentId, List<Permission> permissions) {
        List<Integer> list = new ArrayList<Integer>();
        for (Permission permission : permissions) {
            if ((parentId == null && permission.getParentId() == null) || (parentId != null && permission.getParentId() != null && parentId.intValue() == permission.getParentId().intValue())) {
                list.add(permission.getId());
                list.addAll(getChildrenPermissionIds(permission.getId(), permissions));
            }
        }
        return list;
    }

    /**
     * 获取显示权限
     *
     * @return
     */
    public ResultVO getShowPermissions(Integer rootId) {
        ResultVO resultVO = new ResultVO(true);
        List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();

        //获取我拥有的权限
        List<Permission> myPermissionList = new ArrayList<Permission>();
        //获取所有权限
        List<Permission> permissionList = permissionDao.selectAll();
        Subject subject = SecurityUtils.getSubject();
        for (Permission permission : permissionList) {
            String key = permission.getKey();
            boolean permitted = subject.isPermitted(key);
            if (permitted) {
                myPermissionList.add(permission);
            }
        }

        List<Integer> childrenIds = null;
        if (rootId != null) {
            childrenIds = getChildrenPermissionIds(rootId, permissionList);
            childrenIds.add(rootId);
        }

        List<Permission> rootPermissions = getRootPermissions(myPermissionList);
        for (Permission permission : rootPermissions) {
            if (childrenIds == null || !childrenIds.contains(permission.getId())) {
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("id", permission.getId());
                map.put("text", permission.getName());
                map.put("key", permission.getKey());
                map.put("order", permission.getOrder());
                map.put("children", getChildrenPermissions(myPermissionList, permission.getId(), null,childrenIds));
                mapList.add(map);
            }
        }
        resultVO.setData(mapList);
        return resultVO;
    }

    /**
     * 获取菜单显示权限
     *
     * @param menuId
     * @return
     */
    public ResultVO getMenuShowPermissions(int menuId) {

        ResultVO resultVO = new ResultVO(true);

        List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();

        //获取我拥有的权限
        List<Permission> myPermissionList = new ArrayList<Permission>();
        //获取所有权限
        List<Permission> permissionList = permissionDao.selectAll();
        Subject subject = SecurityUtils.getSubject();
        for (Permission permission : permissionList) {
            String key = permission.getKey();
            boolean permitted = subject.isPermitted(key);
            if (permitted) {
                myPermissionList.add(permission);
            }
        }

        //获取所有菜单
        List<Menu> menus = menuDao.selectAll();
        Menu menu = menuDao.get(menus, menuId);
        if (menu == null) {
            resultVO.setOk(false);
            resultVO.setMsg("菜单不存在");
            return resultVO;
        }

        //获取菜单拥有的权限id
        Set<Integer> permissionIdSet = menuPermissionDao.selectPermissionIdSet(menuId);


        List<Permission> rootPermissions = getRootPermissions(myPermissionList);
        for (Permission permission : rootPermissions) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("id", permission.getId());
            map.put("text", permission.getName());
            map.put("key", permission.getKey());
            map.put("checked", permissionIdSet.contains(permission.getId()));
            map.put("order", permission.getOrder());
            map.put("children", getChildrenPermissions(myPermissionList, permission.getId(), permissionIdSet,null));
            mapList.add(map);
        }
        resultVO.setData(mapList);
        return resultVO;
    }

    /**
     * 获取角色显示权限
     *
     * @param roleId
     * @return
     */
    public ResultVO getRoleShowPermissions(int roleId) {
        ResultVO resultVO = new ResultVO(true);

        List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();

        //获取我拥有的权限
        List<Permission> myPermissionList = new ArrayList<Permission>();
        //获取所有权限
        List<Permission> permissionList = permissionDao.selectAll();
        Subject subject = SecurityUtils.getSubject();
        for (Permission permission : permissionList) {
            String key = permission.getKey();
            boolean permitted = subject.isPermitted(key);
            if (permitted) {
                myPermissionList.add(permission);
            }
        }
        //获取所有角色
        List<Role> roles = roleDao.selectAll();
        Role role = roleDao.get(roles, roleId);
        if (role == null) {
            resultVO.setOk(false);
            resultVO.setMsg("角色不存在");
            return resultVO;
        }
        //获取角色拥有的权限id
        Set<Integer> permissionIdSet = rolePermissionDao.getPermissionIdSetByRoleId(roleId);


        List<Permission> rootPermissions = getRootPermissions(myPermissionList);
        for (Permission permission : rootPermissions) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("id", permission.getId());
            map.put("text", permission.getName());
            map.put("key", permission.getKey());
            map.put("checked", permissionIdSet.contains(permission.getId()));
            map.put("order", permission.getOrder());
            map.put("children", getChildrenPermissions(myPermissionList, permission.getId(), permissionIdSet,null));
            mapList.add(map);
        }
        resultVO.setData(mapList);
        return resultVO;
    }

    private static boolean isKeyExist(List<Permission> list, String key) {
        for (Permission permission : list) {
            if (permission.getKey().equals(key)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 创建权限
     *
     * @param permissionCreateVO
     * @return
     */
    public ResultVO cratePermission(PermissionCreateVO permissionCreateVO) {
        ResultVO resultVO = new ResultVO(true);
        //所有权限
        List<Permission> permissionList = permissionDao.selectAll();
        //查看父级权限是否存在
        Integer parentId = permissionCreateVO.getParentId();
        if (parentId != null) {
            Permission permission = permissionDao.get(permissionList, parentId.intValue());
            if (permission == null) {
                resultVO.setOk(false);
                resultVO.setMsg("父级权限不存在");
                return resultVO;
            }
        }
        //判断权限键值是否存在
        if (isKeyExist(permissionList, permissionCreateVO.getKey())) {
            resultVO.setOk(false);
            resultVO.setMsg("权限键值已存在");
            return resultVO;
        }

        Permission permission = new Permission();
        permission.setKey(permissionCreateVO.getKey());
        permission.setName(permissionCreateVO.getName());
        permission.setParentId(permissionCreateVO.getParentId());
        permission.setOrder(permissionCreateVO.getOrder());
        permissionDao.createPermission(permission);

        resultVO.setMsg("权限创建成功");
        return resultVO;
    }

    //编辑权限
    public ResultVO editPermission(PermissionEditVO permissionEditVO) {
        ResultVO resultVO = new ResultVO(true);
        //获取所有权限
        List<Permission> permissionList = permissionDao.selectAll();

        Permission permission = permissionDao.get(permissionList, permissionEditVO.getId());
        if (permission == null) {
            resultVO.setOk(false);
            resultVO.setMsg("权限不存在");
            return resultVO;
        }

        Permission permissionParent = permissionDao.get(permissionList, permissionEditVO.getParentId());
        if (permissionParent == null) {
            resultVO.setOk(false);
            resultVO.setMsg("上级权限不存在");
            return resultVO;
        }

        if (isKeyExist(permissionList, permissionEditVO.getKey())) {
            if (!permission.getKey().equals(permissionEditVO.getKey())) {
                resultVO.setOk(false);
                resultVO.setMsg("权限键值已存在");
                return resultVO;
            }
        }

        List<Integer> childrenPermissionIds = getChildrenPermissionIds(permissionEditVO.getId(), permissionList);
        childrenPermissionIds.add(permissionEditVO.getId());
        if(childrenPermissionIds.contains(permissionEditVO.getParentId())){
            resultVO.setOk(false);
            resultVO.setMsg("所在权限的上级不能为自己所在权限或者下级权限");
            return resultVO;
        }

        Permission update = new Permission();
        update.setId(permissionEditVO.getId());
        update.setParentId(permissionEditVO.getParentId());
        update.setName(permissionEditVO.getName());
        update.setKey(permissionEditVO.getKey());
        update.setOrder(permissionEditVO.getOrder());
        int num = permissionDao.updatePermission(update);
        if (num == 1) {
            resultVO.setMsg("更新权限成功");
            return resultVO;
        } else {
            resultVO.setOk(false);
            resultVO.setMsg("更新权限失败");
            return resultVO;
        }
    }

    /**
     * 获取子级权限
     *
     * @param permissions
     * @param parentId
     * @return
     */
    public static List<Map<String, Object>> getChildrenPermissions(List<Permission> permissions, Integer parentId, Set<Integer> checkedPermissionIdSet,List<Integer> childrenIdList) {
        List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
        for (Permission permission : permissions) {
            if ((parentId == null && permission.getParentId() == null) || (parentId != null && permission.getParentId() != null && permission.getParentId().intValue() == parentId.intValue())) {
                if(childrenIdList==null||!childrenIdList.contains(permission.getId())) {
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("id", permission.getId());
                    map.put("text", permission.getName());
                    map.put("key", permission.getKey());
                    map.put("checked", checkedPermissionIdSet == null ? false : checkedPermissionIdSet.contains(permission.getId()));
                    map.put("order", permission.getOrder());
                    map.put("children", getChildrenPermissions(permissions, permission.getId(), checkedPermissionIdSet, childrenIdList));
                    mapList.add(map);
                }
            }
        }
        return mapList;
    }

    /**
     * 获取根权限
     *
     * @param permissionList
     * @return
     */
    private List<Permission> getRootPermissions(List<Permission> permissionList) {
        List<Permission> rootPermissions = new ArrayList<Permission>();
        for (Permission permission : permissionList) {
            //如果父级id是null
            if (permission.getParentId() == null) {
                rootPermissions.add(permission);
                continue;
            }
            Permission parentPermission = permissionDao.get(permissionList, permission.getParentId().intValue());
            if (parentPermission == null) {
                rootPermissions.add(permission);
            }
        }
        return rootPermissions;
    }

}
